iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 9
0
Modern Web

Web x Sound - 用 Web 玩轉聲音系列 第 9

Day09 - Media Capture and Streams API

  • 分享至 

  • xImage
  •  

之前我們實作了簡單的播放器,了解該如何播放聲音;前幾天介紹了檔案格式與基礎取樣知識,知道 Web 支援哪些格式的音檔,以及產生音檔背後的原理。接下來講講 Web 提供了哪些 API,可以讓使用者提供音檔,甚至用麥克風錄製聲音吧!

Overview

一共有三個相關的 Web API

API description
Web RTC API (Web Real-Time Communications) 瀏覽器間點對點的即時通訊,可以即時交換影音或任意的資料
Media Capture and Streams API 提供方法操作包含影音的 MediaStream
MediaStream Recording API 提供方法取得 MediaStream、HTMLMediaElement 內含的資料以便進一步處理 (運算、解析、儲存..)

這幾支 API 彼此是互相配合,以提供完整的影音串流操作。

MediaStream

MediaStream 是一個表示影音串流的物件,隸屬於 Media Capture and Streams API,只有一組 input、output,其包含了零至數個 MediaStreamTrack (影音軌),每個 MediaStreamTrack 包含一至數個 Channel (聲道)。

舉個例子:

  • 一首歌曲存放於 MediaStream
  • 有人聲、吉他、鋼琴三種聲音,分別是三個 MediaStreamTrack
  • 人聲是 Stereo 立體聲道 (2 Channels)、吉他鋼琴是 Mono 單聲道 (分別 1 Channel)

Input / Output

[Input]  ==>  MediaStream ==>  [Output]

MediaStream 的產生 (Input)

MediaStream 可以從哪邊取得呢?以下有幾種方式:

Input local / non-local Description
getUserMedia local 從相機、麥克風等裝置使用 navigator.mediaDevices.getUserMedia() 取得資料
media element non-local <audio>, <video> 的 captureStream() 方法
Web Audio API non-local MediaStreamAudioSourceNode 產生的 stream
WebRTC non-local 網路傳輸的 stream 並用 RTCPeerConnection API 取得

當然也可以用 new MediaStream() 建立空的 MediaStream,再把 MediaStreamTrack 塞進去就是了。

MediaStream 能被誰使用 (output)

MediaStream 能被誰使用呢?以下有幾種方式:

Output Description
media element <audio>, <video>
Web Audio API MediaStreamAudioDestinationNode
WebRTC RTCPeerConnection API 取得

method

name description param return
MediaStream() constructor,建立新的 MediaStream MediaStream / Array of MediaStreamTracks MediaStream
addTrack() 加進一軌 MediaStreamTrack undefined
removeTrack() 移除一軌 MediaStreamTrack undefined
clone() 複製整個 MediaStream none MediaStream
getTracks() 返回包含所有 MediaStreamTrack 的陣列,不保證排序 none Array of MediaStreamTracks
getAudioTracks() 返回 MediaStreamTrack.kind 為 audio 的 MediaStreamTrack 陣列,不保證排序 none Array of MediaStreamTracks
getVideoTracks() 返回 MediaStreamTrack.kind 為 video 的 MediaStreamTrack 陣列,不保證排序 none Array of MediaStreamTracks
getTrackById() 返回 MediaStreamTrack.id 與參數 id 相同的 MediaStreamTrack id string MediaStreamTrack or null
onaddtrack event handler for addtrack,新增 track 時觸發
onremovetrack event handler for removetrack,移除 track 時觸發

MediaDevices

MediaDevices 是一個物件,可以取得與本機連結的麥克風、鏡頭、甚至螢幕等裝置。

method

name description param return
ondevicechange event hanlder for devicechange,移除或連接新裝置到電腦時觸發
enumerateDevices() 列舉出與電腦連接的所有裝置 none Promise,包含了 MediaDeviceInfo 物件的陣列
getSupportedConstraints() 列舉出該瀏覽器 MediaStreamTrack 能識別的屬性值,詳情參考這篇 none Object,只包含能識別的屬性值 (key: property, value: true)
getUserMedia() 從裝置取得資料並轉為指定格式的 MediaStream MediaStreamConstraints Promise with stream
navigator.mediaDevices.getUserMedia({ audio: true })
.then(mediaStream => { .... })

MediaStreamTrack

稍微看了一下 API,看起來是沒辦法直接 new 一個 MediaStreamTrack 然後加到 MediaStream。
一定得先建立 MediaStream,取得 MediaStreamTrack 後透過 applyConstraints() 設定讓瀏覽器處理的參數理想值/可接受值 (例如:width: 300 - 600、sampleRate: 44100 ...),從回傳的 Promise 取得處理後的結果。

const constraints = {
  width: {min: 640, ideal: 1280},
  height: {min: 480, ideal: 720},
  advanced: [
    {width: 1920, height: 1280},
    {aspectRatio: 1.333}
  ]
};

navigator.mediaDevices.getUserMedia({ video: true })
.then(mediaStream => {
  const track = mediaStream.getVideoTracks()[0];
  track.applyConstraints(constraints)
  .then(() => { ... }
  .catch(e => { ... }
}

method

name description param return
applyConstraints() 讓 MediaStreamTrack 根據指定屬性值進行處理 MediaTrackConstraints Promise
getCapabilities() 取得瀏覽器 MediaStreamTrack 支援的 constriant 以及有效的屬性值 none MediaTrackCapabilities
getConstraints() 取得 MediaStreamTrack 當前的屬性值 none MediaTrackConstraints
getSettings() 取得 MediaStreamTrack 當前的設定 none MediaTrackSettings
clone() 複製一個 MediaStreamTrack none MediaStreamTrack
stop() 將一個 MediaStreamTrack 停止並 detatch 串流源,一旦串流源沒有任何 track 使用就會完全停止 none none

今天先到這邊,明天再繼續講其他相關的 API 吧~

Reference


上一篇
Day08 - 淺談聲音訊號的轉換
下一篇
Day10 - MediaStream Recording API
系列文
Web x Sound - 用 Web 玩轉聲音13
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言